package com.mxchip.livestar.ui.call

import android.annotation.SuppressLint
import android.media.AudioManager
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat.getSystemService
import androidx.core.view.ViewCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import com.trello.lifecycle2.android.lifecycle.AndroidLifecycle
import com.trello.rxlifecycle3.LifecycleProvider
import com.mxchip.livestar.R
import com.mxchip.livestar.av.camera.CameraHandle
import com.mxchip.livestar.base.SystemData
import com.mxchip.livestar.base.toast
import com.mxchip.livestar.av.camera.HDMIHandle
import com.mxchip.livestar.av.screen.DecoderScreen
import com.mxchip.livestar.original.SendAudioUtil
import com.mxchip.livestar.utils.FileLog
import com.mxchip.livestar.repository.RoomClientRepository
import com.mxchip.livestar.rx.RxBus
import com.mxchip.livestar.rx.RxConstant
import com.mxchip.livestar.rx.RxSchedulersHelper
import com.mxchip.livestar.utils.MyLog
import com.mxchip.livestar.utils.Utils
import com.videohigh.boegam.screenpush.ScreenPushManager
import com.videohigh.graham.SampleSDK
import com.videohigh.graham.SessionContext
import com.videohigh.graham.Term
import io.reactivex.Observable
import kotlinx.android.synthetic.main.fragment_call_control.*
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger

/**
 * 通话控制页面
 */
class CallControlFragment : Fragment() {

    // private val sampleSDK = SampleSDK.getInstance()
    private val roomClientRepository = RoomClientRepository
    private val provider: LifecycleProvider<Lifecycle.Event> = AndroidLifecycle.createLifecycleProvider(this)

    private val dbyViewModel by activityViewModels<DbyViewModel>()

    private val callControlViewModel by activityViewModels<CallControlViewModel>()
    private val roomViewModel by activityViewModels<RoomViewModel>()
    private val screenViewModel by activityViewModels<ScreenViewModel>()


    // private lateinit var hangupEventObservable: Observable<HangupEvent>
    private lateinit var leaveCallEventObservable: Observable<SessionContext>

    //通话中有其他用户被邀请进来，显示未接状态
    private lateinit var invitedEventObservable: Observable<SessionContext>
    private lateinit var enterEventObservable: Observable<SessionContext>
    private lateinit var disconnectEventObservable: Observable<Boolean>
    private lateinit var disconnectReasonEventObservable: Observable<String>
    private lateinit var reconnectEventObservable: Observable<Boolean>


    private lateinit var busyResPubCloseObservable: Observable<Boolean>

    /**
     * 通话中断网提示
     */
    val dialog: AlertDialog by lazy {
        AlertDialog.Builder(requireContext()).setTitle(getString(R.string.tips)).setMessage(getString(R.string.check_net)).setPositiveButton(getString(R.string.sure_str)) { _, _ ->
            RoomClientRepository.disconnect()
            RoomClientRepository.connect()
            keepAndSyncAlive()
        }.setCancelable(false).create()
    }
   val hangUpDialog: AlertDialog by lazy {
        AlertDialog.Builder(requireContext()).setTitle(getString(R.string.tips)).setMessage("已在其他端登录,请退出").setPositiveButton(getString(R.string.sure_str)) { _, _ ->
            RoomClientRepository.disconnect()
            RoomClientRepository.connect()
            keepAndSyncAlive()
        }.setCancelable(false).create()
    }

    private val logger: FileLog = FileLog.getLogger(CallControlFragment::class.java)

    private var keepAliveJob: Job? = null

    private val mAudioManage by lazy {
        context?.let { getSystemService(it, AudioManager::class.java) }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        MyLog.logD(MyLog.CALL_CONTROL_FRAGMENT_MODEL, "CallControlFragment::onDestroyView ")
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        // Inflate the layout for this fragment
        val view = inflater.inflate(R.layout.fragment_call_control, container, false)

        ViewCompat.setTranslationZ(view, -1f)

        return view
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        MyLog.logD(MyLog.CALL_CONTROL_FRAGMENT_MODEL, "CallControlFragment::onCreate ")
        initRxBus()
        openDevices()
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)




        button_mic.setOnClickListener {
            logger.info(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) + " onMicClick ${!dbyViewModel.mic.value!!}");
            dbyViewModel.mic(!dbyViewModel.mic.value!!)
        }



        button_camera.setOnClickListener {
            // callControlViewModel.touched()
            logger.info(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) + " onCameraClick ${!dbyViewModel.camera.value!!}");
            dbyViewModel.camera(!dbyViewModel.camera.value!!)
        }


        button_hangup.setOnClickListener {
            // callControlViewModel.touched()
            logger.info(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) + " onHangupClick");
            reqHangup()
        }

        button_hide_small_view.setOnClickListener {

            val mainScreenMode = screenViewModel.mainScreenMode()

            if (!mainScreenMode) {
                text_hide_small_view.text = getString(R.string.show_small_view)
            } else {
                text_hide_small_view.text = getString(R.string.hide_small_view)
            }

            screenViewModel.mainScreenMode(!mainScreenMode)
        }

        button_invite.setOnClickListener {

            if (!Utils.isFastClick()) {
                keepAndSyncAlive()
                findNavController().navigate(R.id.action_callControlFragment_to_inviteDialogFragment)
            }

        }


        button_hdmi.setOnClickListener {
            if (canNotShareScreen()) return@setOnClickListener
            findNavController().navigate(R.id.action_callControlFragment_to_hdmiScreenDialogFragment)

            /*callControlViewModel.touched()
            if (SystemData.getInstance().streamMode == StreamMode.RECEIVE_DOUBLE) {
                toast(getString(R.string.can_not_screen_at_same_time))
                return
            }
            if (SystemData.getInstance().getWifiResPub()) {
                toast(getString(R.string.can_not_use_wirelses))
                return
            }
            if (Utils.isFastClick()) {
                return
            }
            dbyViewModel.hdmi(!dbyViewModel.hdmi.value!!)*/
        }

        button_volume.setOnClickListener {
            mAudioManage?.adjustStreamVolume(AudioManager.STREAM_VOICE_CALL, AudioManager.ADJUST_SAME, AudioManager.FLAG_SHOW_UI)
        }
        val resType = AtomicInteger(AVDevice.NONE_RES)
        dbyViewModel.extMicType.observe(viewLifecycleOwner, Observer { type ->
            val oldType = resType.getAndSet(type)
            if (type == AVDevice.HDMI_RES) {
                RxBus.get().post(RxConstant.GET_HDMI_AUDIO, true)
            } else if (type == AVDevice.WIFI_RES) {
                RxBus.get().post(RxConstant.BUSY_RES_AUDIO_PUB, true)
            } else {
                if (oldType == AVDevice.HDMI_RES) {
                    RxBus.get().post(RxConstant.GET_HDMI_AUDIO, false)
                } else if (oldType == AVDevice.WIFI_RES) {
                    RxBus.get().post(RxConstant.BUSY_RES_AUDIO_PUB, false)
                }
            }
        })

        screenViewModel.screenSettings.observe(viewLifecycleOwner, {

            val streamingAVDevices = screenViewModel.streamingAVDevices.value?.toList()

            val nextOnScreenAVDevices = it?.allScreens?.filterIsInstance<DecoderScreen>()?.map { screen ->
                // AVDevice(screen.deviceUid, screen.deviceName)
                screen.videoDevice
            }

            streamingAVDevices?.forEach { avDevice ->
                if ((nextOnScreenAVDevices == null || !nextOnScreenAVDevices.contains(avDevice))) {
                    // if (avDevice.deviceName != AVDevice.CAMERA_HDMI && avDevice.deviceName != AVDevice.CAMERA_WIFI) {
                        val result = RoomClientRepository.muteRemoteVideoStream(avDevice, true)
                        Log.e("CallActivityA", "muteRemoteVideoStream true: result $result avDevice:${avDevice}")
                    // }
                    screenViewModel.removeStreamingAVDevice(avDevice)
                }
            }

            nextOnScreenAVDevices?.forEach { avDevice ->
                // if (avDevice.deviceName != AVDevice.CAMERA_HDMI && avDevice.deviceName != AVDevice.CAMERA_WIFI) {
                    val result = RoomClientRepository.muteRemoteVideoStream(avDevice, false)
                    Log.e("CallActivityA", "muteRemoteVideoStream false: result $result avDevice:${avDevice}")
                // }
                screenViewModel.addStreamingAVDevice(avDevice)
            }

        })

        roomViewModel.audioDevices.observe(viewLifecycleOwner, { audioList ->
            audioList.forEach {
                //TODO:1.开启远端音频流每次操作的都是一组数据,应当只操作对应变化的数据 2.应该收到AVideoState.STOP调用关闭音频设备
                logger.info("CallActivityA::onCreate audioList:muteRemoteAudioStream false:${it}")
                RoomClientRepository.muteRemoteAudioStream(it, false)
            }
        })

        dbyViewModel.camera.observe(viewLifecycleOwner, { isOpen ->

            screenViewModel.frontCameraPreview(isOpen)

            if (isOpen) {

                RoomClientRepository.addVideoDevice(arrayOf(AVDevice.CAMERA_LOCAL, AVDevice.CAMERA_LOCAL_SMALL), {

                }, { code, message ->

                })

                button_camera.isSelected = false
                button_camera.setImageResource(R.drawable.icon_incall_camera_button)
                text_camera.text = getString(R.string.close_camera)
            } else {

                RoomClientRepository.removeVideoDevice(arrayOf(AVDevice.CAMERA_LOCAL, AVDevice.CAMERA_LOCAL_SMALL), {

                }, { errorCode, message ->

                })

                button_camera.isSelected = true
                button_camera.setImageResource(R.drawable.icon_incall_camera_off_button)
                text_camera.text = getString(R.string.open_camera)
            }
        })

        dbyViewModel.mic.observe(viewLifecycleOwner, Observer { enable ->

            if (!enable) {
                val result = RoomClientRepository.removeAudioDevice(AVDevice.AUDIO_BUILD_IN, {}, { code, message ->})
                Log.e("CallActivity", "mic result: $result enable:$enable")
                button_mic.isSelected = true
                button_mic.setImageResource(R.drawable.icon_incall_mic_off_button)
                text_mic.text = getString(R.string.open_mic)
            } else {
                val result = RoomClientRepository.addAudioDevice(AVDevice.AUDIO_BUILD_IN, {}, { code, message ->})
                Log.e("CallActivity", "mic result: $result enable:$enable")
                button_mic.isSelected = false
                button_mic.setImageResource(R.drawable.icon_incall_mic_button)
                text_mic.text = getString(R.string.clse_mic)
            }
        })
//        dbyViewModel.userIds.observe(viewLifecycleOwner, Observer { list ->
//            if (list != null && list.size == 1 && list[0] == SystemData.userId && RoomClientRepository.state.value == RoomClientRepository.State.BUSY) {
//                MyLog.logD("hangup userIds size is 1---->")
//                Log.d("CallControlFragment", "AutoHangup-----dbyViewModel.userIds size is 1")
//                // reqHangup()
//                // dbyViewModel.join(null)
//            }
//            MyLog.logD("CallControlFragment::userIds $list")
//        })


//        roomViewModel.sessionsAll.observe(viewLifecycleOwner, Observer {
//            Log.d("CallControlFragment", "sessionsAll----- ${it.toTypedArray().contentToString()}")
//        })


        dbyViewModel.hdmi.observe(viewLifecycleOwner, Observer { show ->

            if (show && dbyViewModel.shareScreen.value == AVDevice.NONE_RES) {

                RoomClientRepository.addShareContent(AVDevice.CAMERA_HDMI, {
                    MyLog.logD(MyLog.SHARE_CONTENT_MODEL, "CallControlFragment:: dbyViewModel.hdmi RoomClientRepository.addShareContent")

                    dbyViewModel.showHDMIView(true)
                    CameraHandle.getInstance().setEncoderBitRate(1024 * 512)
                    hdmiApplyIFrame(2)
                    dbyViewModel.resShareResponse(true)

                }, { errorCode, message ->
                    dbyViewModel.hdmi(false)
                    activity?.runOnUiThread { toast("不能同时进行屏幕共享") }
                })

            } else if (!show && dbyViewModel.shareScreen.value == AVDevice.HDMI_RES) {

                RoomClientRepository.removeShareContent(AVDevice.CAMERA_HDMI, { resp ->
                    MyLog.logD(MyLog.SHARE_CONTENT_MODEL, "CallControlFragment:: dbyViewModel.hdmi RoomClientRepository.removeShareContent")

                    dbyViewModel.showHDMIView(false)
                    dbyViewModel.resShareResponse(false)
                    CameraHandle.getInstance().setEncoderBitRate(1024 * 1024 * 3 / 2)

                }, { errorCode, message ->

                })

            }
        })

        roomViewModel.isMyselfTheOnlyOneLeft.observe(viewLifecycleOwner, Observer {
            if (it == true) { // && !dbyViewModel.join().value.isNullOrEmpty()) {
                logger.info(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) + " CallControlFragment hangup sessionsCall size <= 1---->");
                reqHangup()
            }
        })

        callControlViewModel.isShow().observe(viewLifecycleOwner, Observer { isShow ->
            group_toolbar.apply {
                visibility = if (!isShow) View.INVISIBLE else View.VISIBLE
            }.requestLayout()
        })

        callControlViewModel.isLongClick().observe(viewLifecycleOwner, Observer {
            if (it) {
                findNavController().navigate(R.id.action_callControlFragment_to_adminFragment)
            }
        })
        /*dbyViewModel.hideSmallView.observe(viewLifecycleOwner, Observer { hideSmallView ->
            run {
                if (hideSmallView) {
                    text_hide_small_view.text = getString(R.string.show_small_view)
                } else {
                    text_hide_small_view.text = getString(R.string.hide_small_view)
                }
            }
        })*/


        /*dbyViewModel.callControlTouched.observe(viewLifecycleOwner, Observer { touched ->
            callControlViewModel.touched()
        })*/

//        onRootContainerClick(view)


        keepAliveJob = lifecycleScope.launch {
            while (true) {

                RoomClientRepository.keepAliveChannel({

                }, { code, message ->

                    if (keepAliveJob?.isCancelled != false) {
                        lifecycleScope.launch {
                            toast("当前网络差，正在退出通话...")
                            delay(1500)
                            logger.info(SimpleDateFormat("yyyy-MM-dd-HH:mm:ss", Locale.CHINA).format(Date()) + " loop keepAliveChannel reqHangup")
                            reqHangup()
                        }
                    }
                })

                delay(5000)
            }
        }

        lifecycleScope.launch {
            while (true) {

                keepAndSyncAlive()

                delay(30*1000)
            }
        }
    }


    /**
     * 开启设备
     */
    private fun openDevices() {
        dbyViewModel.mic(true)
        dbyViewModel.camera(true)
        SendAudioUtil.getInstance().start()
    }

    @SuppressLint("CheckResult")
    private fun initRxBus() {
        MyLog.logD(MyLog.CALL_CONTROL_FRAGMENT_MODEL, "CallControlFragment::initRxBus ")

        //通话中添加成员-通知已经在房间中的人
        invitedEventObservable = RxBus.get().register(RxConstant.INVITATED_EVENT, SessionContext::class.java)
        invitedEventObservable./*compose(provider.bindToLifecycle()).*/compose(RxSchedulersHelper.io_main())
                .subscribe(::onInvited) { error ->
                    run {
                        logger.error(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) +
                                " invitationEventObservable" + error.message)
                        error.printStackTrace()
                    }
                }

        leaveCallEventObservable = RxBus.get().register(RxConstant.LEAVE_CALL_EVENT, SessionContext::class.java)
        leaveCallEventObservable./*compose(provider.bindToLifecycle()).*/compose(RxSchedulersHelper.io_main())
                .subscribe(::onLeaveCall) { error ->
                    run {
                        logger.error(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) +
                                " leaveCallEventObservable" + error.message)
                        error.printStackTrace()
                    }
                }

        //被动挂断
        /*hangupEventObservable = RxBus.get().register(RxConstant.HANGUP_EVENT, HangupEvent::class.java)
        hangupEventObservable.*//*compose(provider.bindToLifecycle()).*//*compose(RxSchedulersHelper.io_main())
                .subscribe(::onHangup) { error ->
                    run {
                        logger.error(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) +
                                " hangupEventObservable" + error.message)
                        error.printStackTrace()
                    }
                }*/

        //主叫收到被叫的 接听/挂断 消息
        enterEventObservable = RxBus.get().register(RxConstant.ENTER_EVENT, SessionContext::class.java)
        enterEventObservable./*compose(provider.bindToLifecycle()).*/compose(RxSchedulersHelper.io_main())
                .subscribe(::onEnter) { error ->
                    run {
                        logger.error(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) +
                                " enterEventObservable" + error.message)
                        error.printStackTrace()
                    }
                }


        //开启关闭 无线投屏按钮
        busyResPubCloseObservable = RxBus.get().register(RxConstant.RES_VIDEO_PUB_NOTIFY, Boolean::class.java)
        busyResPubCloseObservable./*compose(provider.bindToLifecycle()).*/compose(RxSchedulersHelper.io_main())
                .subscribe(::busyResPubCloseObservable) { error ->
                    run {
                        logger.error(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) +
                                " busyResPubCloseObservable" + error.message)
                        error.printStackTrace()
                    }
                }

        disconnectEventObservable = RxBus.get().register(RxConstant.DISCONNECT, Boolean::class.java)
        disconnectEventObservable./*compose(provider.bindToLifecycle()).*/compose(RxSchedulersHelper.io_main())
                .subscribe(::onDisconnect) { error ->
                    run {
                        logger.error(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) +
                                " disconnectEventObservable" + error.message)
                        error.printStackTrace()
                    }
                }


        disconnectReasonEventObservable = RxBus.get().register(RxConstant.DISCONNECT_REASON, String::class.java)
        disconnectReasonEventObservable./*compose(provider.bindToLifecycle()).*/compose(RxSchedulersHelper.io_main())
                .subscribe(::onDisconnectReason) { error ->
                    run {
                        logger.error(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) +
                                " disconnectReasonEventObservable " + error.message)
                        error.printStackTrace()
                    }
                }


        reconnectEventObservable = RxBus.get().register(RxConstant.RECONNECT, Boolean::class.java)
        reconnectEventObservable./*compose(provider.bindToLifecycle()).*/compose(RxSchedulersHelper.io_main())
                .subscribe(::onReConnect) { error ->
                    run {
                        logger.error(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) +
                                " reconnectEventObservable" + error.message)
                        error.printStackTrace()
                    }
                }

    }


    override fun onDestroy() {
        super.onDestroy()
        MyLog.logD(MyLog.CALL_CONTROL_FRAGMENT_MODEL, "CallControlFragment::onDestroy: ")

        // RoomClientRepository.sync(null)
        // RxBus.get().unregister(RxConstant.ACTIVE_HANGUP, hangupBeanObservable)

        RxBus.get().unregister(RxConstant.LEAVE_CALL_EVENT, leaveCallEventObservable)
        // RxBus.get().unregister(RxConstant.HANGUP_EVENT, hangupEventObservable)
        // RxBus.get().unregister(RxConstant.BUSY_MUL_INVITE_REQUEST, busyMulInviteRequestObservable)
        RxBus.get().unregister(RxConstant.INVITATED_EVENT, invitedEventObservable)
        // RxBus.get().unregister(RxConstant.BUSY_RES_CLOSE_NOTIFY, busyResCloseNotifyObservable)
        // RxBus.get().unregister(RxConstant.BUSY_RES_PUB_NOTIFY, busyResPubNotifyObservable)

        RxBus.get().unregister(RxConstant.ENTER_EVENT, enterEventObservable)
        RxBus.get().unregister(RxConstant.RES_VIDEO_PUB_NOTIFY, busyResPubCloseObservable)

        RxBus.get().unregister(RxConstant.DISCONNECT, disconnectEventObservable)
        RxBus.get().unregister(RxConstant.DISCONNECT_REASON, disconnectReasonEventObservable)
        RxBus.get().unregister(RxConstant.RECONNECT, reconnectEventObservable)
    }

    /**
     * 关闭视频共享
     */
    private fun busyResPubCloseObservable(aBoolean: Boolean) {

        // MyLog.logD(MyLog.SHARE_CONTENT_MODEL, "CallControlFragment::busyResPubCloseObservable: aBoolean:${aBoolean} roomId:${roomId} channelId:${channelId} callIndex:${callIndex}  ")
        if (aBoolean && dbyViewModel.shareScreen.value == AVDevice.NONE_RES) {
            MyLog.logD(MyLog.SHARE_CONTENT_MODEL, "CallControlFragment::busyResPubCloseObservable: roomViewModel.avDevices.value!!.size:${roomViewModel.avDevices.value!!.size}  ")
            if (canNotShareScreen()) return

            RoomClientRepository.addShareContent(AVDevice.CAMERA_WIFI, {
                MyLog.logD(MyLog.SHARE_CONTENT_MODEL, "CallControlFragment::RoomClientRepository.addShareContent")

                SystemData.getInstance().wifiResPub = true
                dbyViewModel.showWiFiView(true)
                CameraHandle.getInstance().setEncoderBitRate(1024 * 512)
                hdmiApplyIFrame(2)
                dbyViewModel.resShareResponse(true)

            }, { code, message ->
                activity?.runOnUiThread {
                    ScreenPushManager.getInstance().close()
                }
            })


        } else if (!aBoolean && dbyViewModel.shareScreen.value == AVDevice.WIFI_RES) {

            RoomClientRepository.removeShareContent(AVDevice.CAMERA_WIFI, {
                MyLog.logD(MyLog.SHARE_CONTENT_MODEL, "CallControlFragment::RoomClientRepository.removeShareContent")
                dbyViewModel.showWiFiView(false)
                dbyViewModel.resShareResponse(false)
                CameraHandle.getInstance().setEncoderBitRate(1024 * 1024 * 3 / 2)
                ScreenPushManager.getInstance().close()
            } , { code, message ->

            })

        }
    }

    private fun canNotShareScreen(): Boolean {
//        if (!roomViewModel.groupId.value.isNullOrEmpty() && roomViewModel.avDevices.value!!.isEmpty()) {
//            ScreenPushNative.nativeMAINConnOpt(0, GeneralConst.JNI_STATUS_CLOSE_V)
//            toast("待其它参会人员进入后进行屏幕共享")
//            return true
//        }
        return false
    }


    /**
     * 有成员加入会议（会议前）
     */
    private fun onEnter(sessionContext: SessionContext) {
        Log.e("CallControlFragment", "respInviteAccept: $sessionContext")
    }


    /**
     * 申请I帧
     */
    @SuppressLint("CheckResult")
    private fun hdmiApplyIFrame(count: Int) {
        Observable.interval(1000, 1000, TimeUnit.MILLISECONDS)
                .compose(provider.bindToLifecycle())
                .compose(RxSchedulersHelper.io())
                .take(count.toLong())
                .subscribe { aLong -> HDMIHandle.getInstance().applyIFrame() }
    }


    /**
     * 有成员加入会议（会议中）
     */
    private fun onInvited(sessionContext: SessionContext) {
        logger.info(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) +
                " busyAddMemberView InvitationEvent:" + sessionContext)

        /*lifecycleScope.launch {
            roomViewModel.setSessionContext(sessionContext)
        }*/
    }

    /**
     * 断网重连
     */
    private fun onReConnect(v: Boolean) {
        disconnectHangupJob?.cancel()
        keepAndSyncAlive()

    }

    /**
     * 同步数据并保持心跳
     */
    private fun keepAndSyncAlive() {
        lifecycleScope.launch {

            while (!RoomClientRepository.connected()) {
                delay(1)
            }

            roomClientRepository.syncAndKeepAliveChannel({ session ->
                /*lifecycleScope.launch {
                    roomViewModel.setSessionContext(session)
                }*/

            } , { code, message ->

                lifecycleScope.launch {
                    toast("当前网络差，正在退出通话...")
                    delay(1500)
                    logger.info(SimpleDateFormat("yyyy-MM-dd-HH:mm:ss", Locale.CHINA).format(Date()) + " onReConnect keepAliveChannel reqHangup")
                    reqHangup()
                }
            })
        }
    }

    private var disconnectHangupJob: Job? = null

    /**
     * 断网回调
     */
    private fun onDisconnect(v: Boolean) {
        toast("当前网络差，正在尝试重连...")
        disconnectHangupJob = lifecycleScope.launch {
            delay(30 * 1000)
            reqHangup()
        }
    }

    /**
     * 断网原因回调
     */
    private fun onDisconnectReason(v: String) {
        logger.info(SimpleDateFormat("yyyy-MM-dd-HH:mm:ss", Locale.CHINA).format(Date()) +
                "CallControlFragment::onDisconnectReason:   v:$v")
        toast("onDisconnectReason v:$v")
        if (v == "KickOff") {
            lifecycleScope.launch {
                if (!dialog.isShowing)
                    dialog.show()
            }
        }else{
            lifecycleScope.launch {
                if (!dialog.isShowing)
                    dialog.show()
            }
        }
    }

    /**
     * 请求挂断
     */
    private fun reqHangup() {

        logger.info(SimpleDateFormat("yyyy-MM-dd-HH:mm:ss", Locale.CHINA).format(Date()) + " Event.hungupBtnClick reqHangup")

        keepAliveJob?.cancel()

        RoomClientRepository.endCall {
            dbyViewModel.join(null)
        }
    }

    /**
     * 通话中有人挂断
     */
    private fun onLeaveCall(session: SessionContext) {

        Log.e("CallControlFragment", "onLeaveCall: $session")
        MyLog.logD(MyLog.SIGNALLING_MODEL, "signaling server respRelease removeTermId(bean):${session} ---->")
        logger.info(SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(Date()) +
                "CallControlFragment::onLeaveCall: roomViewModel.videoDevices:${session}")

        // roomViewModel.setSessionContext(session)
    }

}